/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package cmsc427.mw5;

import cmsc427.mw5.BluetoothChatService;
import cmsc427.mw5.app.Contact;
import cmsc427.mw5.app.ContactAdapter;
import cmsc427.mw5.R;
import cmsc427.mw5.app.ContactList;
import cmsc427.mw5.snake.Snake;
import cmsc427.mw5.app.ScrollableWebView;
import android.app.Activity;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

/**
 * This is the main Activity that displays the current chat session.
 */
public class BluetoothChat extends Activity {
	public static final String BROADCAST_MOTION_ACTION = "motion_gesture";
	public static final String BROADCAST_MOTION_NAME = "cmsc427.mw5.motion.direction";
	public static final String BROADCAST_MOTION_UP = "quickup";
	public static final String BROADCAST_MOTION_DOWN = "quickdown";
	public static final String BROADCAST_MOTION_LEFT = "left";
	public static final String BROADCAST_MOTION_RIGHT = "right";
	
	// Debugging
	private static final String TAG = "BluetoothChat";
	private static final boolean D = true;

	// Message types sent from the BluetoothChatService Handler
	public static final int MESSAGE_STATE_CHANGE = 1;
	public static final int MESSAGE_READ = 2;
	public static final int MESSAGE_WRITE = 3;
	public static final int MESSAGE_DEVICE_NAME = 4;
	public static final int MESSAGE_TOAST = 5;
	public static final int MESSAGE_READ_STRING = 6;

	// Key names received from the BluetoothChatService Handler
	public static final String DEVICE_NAME = "device_name";
	public static final String TOAST = "toast";

	// Intent request codes
	private static final int REQUEST_CONNECT_DEVICE = 1;
	private static final int REQUEST_ENABLE_BT = 2;

	// Layout Views
	private EditText mOutEditText;

	// Name of the connected device
	private String mConnectedDeviceName = null;

	// String buffer for outgoing messages
	private StringBuffer mOutStringBuffer;
	// Local Bluetooth adapter
	private BluetoothAdapter mBluetoothAdapter = null;
	// Member object for the chat services
	private BluetoothChatService mChatService = null;

	private static MotionReceiver motionReceiver;
	private IntentFilter intentFilter;
	
	//private ContactAdapter contacts;	
	
	Button btnShowContacts;
	
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		if (D){
			Log.e(TAG, "+++ ON CREATE +++");
		}
		
		// Set up the window layout
		setContentView(R.layout.main);

		// Get local Bluetooth adapter
		mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

		// If the adapter is null, then Bluetooth is not supported
		if (mBluetoothAdapter == null) {
			Toast.makeText(this, "Bluetooth is not available",
					Toast.LENGTH_LONG).show();
			finish();
			return;
		}
		
		super.onCreate(savedInstanceState);
			
		// register broadcast receivers*/
		motionReceiver = new MotionReceiver(this);
		intentFilter = new IntentFilter(BROADCAST_MOTION_ACTION);
		registerReceiver(motionReceiver, intentFilter);
	}
	
    protected void launchContactList() {
        Intent i = new Intent(this, ContactList.class);
        startActivity(i);
    }
    
    protected void launchSnake(){
    	Intent i = new Intent(this, Snake.class);
    	startActivity(i);
    }
    
    protected void launchBrowser(){
    	Intent i = new Intent(this, ScrollableWebView.class);
    	startActivity(i);
    }

	@Override
	public void onStart() {
		super.onStart();
		if (D)
			Log.e(TAG, "++ ON START ++");

		// If BT is not on, request that it be enabled.
		// setupChat() will then be called during onActivityResult
		if (!mBluetoothAdapter.isEnabled()) {
			Intent enableIntent = new Intent(
					BluetoothAdapter.ACTION_REQUEST_ENABLE);
			startActivityForResult(enableIntent, REQUEST_ENABLE_BT);
			// Otherwise, setup the chat session
		} else {
			if (mChatService == null)
				setupChat();
				
		}
	}

	@Override
	public synchronized void onResume() {
		super.onResume();
		if (D)
			Log.e(TAG, "+ ON RESUME +");

		// Performing this check in onResume() covers the case in which BT was
		// not enabled during onStart(), so we were paused to enable it...
		// onResume() will be called when ACTION_REQUEST_ENABLE activity
		// returns.
		if (mChatService != null) {
			// Only if the state is STATE_NONE, do we know that we haven't
			// started already
			if (mChatService.getState() == BluetoothChatService.STATE_NONE) {
				// Start the Bluetooth chat services
				mChatService.start();
				
			}
			//mChatService = new BluetoothChatService(this, mHandler);
			//mChatService.start();
		
		}
		
		registerReceiver(motionReceiver, intentFilter);
	}

	private void setupChat() {
		Log.d(TAG, "setupChat()");

		// Initialize the BluetoothChatService to perform bluetooth connections
		mChatService = new BluetoothChatService(this, mHandler);

		// Initialize the buffer for outgoing messages
		mOutStringBuffer = new StringBuffer("");
		
		sendMessage("1");
	}

	@Override
	public synchronized void onPause() {
		super.onPause();
		if (D)
			Log.e(TAG, "- ON PAUSE -");
		
			
	}

	@Override
	public void onStop() {
		super.onStop();
		if (D)
			Log.e(TAG, "-- ON STOP --");
	}

	@Override
	public void onDestroy() {
		super.onDestroy();
		// Stop the Bluetooth chat services
		if (mChatService != null)
			mChatService.stop();
		if (D)
			Log.e(TAG, "--- ON DESTROY ---");
	}

	/**
	 * Sends a message.
	 * 
	 * @param message
	 *            A string of text to send.
	 */
	private void sendMessage(String message) {
		// Check that we're actually connected before trying anything
		if (mChatService.getState() != BluetoothChatService.STATE_CONNECTED) {
			Toast.makeText(this, R.string.not_connected, Toast.LENGTH_SHORT)
					.show();
			return;
		}

		// Check that there's actually something to send
		if (message.length() > 0) {
			// Get the message bytes and tell the BluetoothChatService to write
			byte[] send = message.getBytes();
			mChatService.write(send);

			// Reset out string buffer to zero and clear the edit text field
			mOutStringBuffer.setLength(0);
			mOutEditText.setText(mOutStringBuffer);
		}
	}

	// The action listener for the EditText widget, to listen for the return key
	private TextView.OnEditorActionListener mWriteListener = new TextView.OnEditorActionListener() {
		public boolean onEditorAction(TextView view, int actionId,
				KeyEvent event) {
			// If the action is a key-up event on the return key, send the
			// message
			if (actionId == EditorInfo.IME_NULL
					&& event.getAction() == KeyEvent.ACTION_UP) {
				String message = view.getText().toString();
				sendMessage(message);
			}
			if (D)
				Log.i(TAG, "END onEditorAction");
			return true;
		}
	};

	// The Handler that gets information back from the BluetoothChatService
	private final Handler mHandler = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			switch (msg.what) {
			case MESSAGE_STATE_CHANGE:
				if (D)
					Log.i(TAG, "MESSAGE_STATE_CHANGE: " + msg.arg1);
				switch (msg.arg1) {
				case BluetoothChatService.STATE_CONNECTED:
					Log.i(TAG, "STATE CONNECTED");
					//mTitle.setText(R.string.title_connected_to);
					//mTitle.append(mConnectedDeviceName);
					//mConversationArrayAdapter.clear();
					break;
				case BluetoothChatService.STATE_CONNECTING:
					Log.i(TAG, "STATE CONNECTING");
					//mTitle.setText(R.string.title_connecting);
					break;
				case BluetoothChatService.STATE_LISTEN:
				case BluetoothChatService.STATE_NONE:
					Log.i(TAG, "STATE NOT CONNECTED");
					//mTitle.setText(R.string.title_not_connected);
					break;
				}
				break;
			case MESSAGE_WRITE:
				byte[] writeBuf = (byte[]) msg.obj;
				// construct a string from the buffer
				String writeMessage = new String(writeBuf);
				//mConversationArrayAdapter.add("Me:  " + writeMessage);
				break;
			case MESSAGE_READ:
				byte[] readBuf = (byte[]) msg.obj;
				
				// construct a string from the valid bytes in the buffer
				String readMessage = new String(readBuf, 0, msg.arg1);				
				
				// prints the message on the screen fetched from the accelerometer
				//mConversationArrayAdapter.add(readMessage);
				
				break;
			case MESSAGE_READ_STRING:
				if(msg.obj.getClass().equals(String.class)){
					//byte[] readBufStr = (byte[]) msg.obj;
					
					// construct a string from the valid bytes in the buffer
					
					String gesture = (String)msg.obj;
					
					Intent intent = new Intent(BROADCAST_MOTION_ACTION);
					
					intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
					
					Log.i("MOTION", gesture);
					
					if(gesture.equalsIgnoreCase(BROADCAST_MOTION_LEFT)){
						intent.putExtra(BROADCAST_MOTION_NAME, BROADCAST_MOTION_LEFT);
					}
					else if(gesture.equalsIgnoreCase(BROADCAST_MOTION_UP)){
						intent.putExtra(BROADCAST_MOTION_NAME, BROADCAST_MOTION_UP);
					}
					else if(gesture.equalsIgnoreCase(BROADCAST_MOTION_RIGHT)){
						intent.putExtra(BROADCAST_MOTION_NAME, BROADCAST_MOTION_RIGHT);
					}
					else if(gesture.equalsIgnoreCase(BROADCAST_MOTION_DOWN)){
						intent.putExtra(BROADCAST_MOTION_NAME, BROADCAST_MOTION_DOWN);
					}
					
					sendBroadcast(intent);
					
					//String readMessageString = new String(readBufStr, 0, msg.arg1);				
					
					// prints the message on the screen fetched from the accelerometer
					//mConversationArrayAdapter.add((String)msg.obj);
				}
				break;
			case MESSAGE_DEVICE_NAME:
				// save the connected device's name
				
				mConnectedDeviceName = msg.getData().getString(DEVICE_NAME);
				Log.i(TAG, mConnectedDeviceName);
				Toast.makeText(getApplicationContext(),
						"Connected to " + mConnectedDeviceName,
						Toast.LENGTH_SHORT).show();
				break;
			case MESSAGE_TOAST:
				Toast.makeText(getApplicationContext(),
						msg.getData().getString(TOAST), Toast.LENGTH_SHORT)
						.show();
				break;
			}
		}
	};

	@Override
	public void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (D)
			Log.d(TAG, "onActivityResult " + resultCode);
		switch (requestCode) {
		case REQUEST_CONNECT_DEVICE:
			// When DeviceListActivity returns with a device to connect
			if (resultCode == Activity.RESULT_OK) {
				// Get the device MAC address
				String address = data.getExtras().getString(
						DeviceListActivity.EXTRA_DEVICE_ADDRESS);
				// Get the BLuetoothDevice object
				BluetoothDevice device = mBluetoothAdapter
						.getRemoteDevice(address);
				// Attempt to connect to the device
				mChatService.connect(device);
			}
			break;
		case REQUEST_ENABLE_BT:
			// When the request to enable Bluetooth returns
			if (resultCode == Activity.RESULT_OK) {
				// Bluetooth is now enabled, so set up a chat session
				setupChat();
			} else {
				// User did not enable Bluetooth or an error occured
				Log.d(TAG, "BT not enabled");
				Toast.makeText(this, R.string.bt_not_enabled_leaving,
						Toast.LENGTH_SHORT).show();
				finish();
			}
		}
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getMenuInflater();
		inflater.inflate(R.menu.option_menu, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case R.id.scan:
			// Launch the DeviceListActivity to see devices and do scan
			Intent serverIntent = new Intent(this, DeviceListActivity.class);
			startActivityForResult(serverIntent, REQUEST_CONNECT_DEVICE);
			return true;
		}
		return false;
	}

	
        
    private static class MotionReceiver extends BroadcastReceiver {

    	private BluetoothChat list;
    	
    	public MotionReceiver(BluetoothChat bluetoothChat) {
    		this.list = bluetoothChat;
    		Log.i(TAG, "MotionReceiver Created");
    	}
    	
		@Override
		public void onReceive(Context context, Intent intent) {
			Log.i(TAG, "MOTION");
			
			if(intent.getExtras().get(BROADCAST_MOTION_NAME).equals(BROADCAST_MOTION_UP)){
				context.unregisterReceiver(motionReceiver);
				list.launchBrowser();
			} else if(intent.getExtras().get(BROADCAST_MOTION_NAME).equals(BROADCAST_MOTION_DOWN)){
				
			} else if(intent.getExtras().get(BROADCAST_MOTION_NAME).equals(BROADCAST_MOTION_LEFT)){
				context.unregisterReceiver(motionReceiver);
				list.launchContactList();
			}
			else if (intent.getExtras().get(BROADCAST_MOTION_NAME).equals(BROADCAST_MOTION_RIGHT)){
				context.unregisterReceiver(motionReceiver);
				list.launchSnake();	
			}
			
		}

    }


}